﻿using System;
using System.Windows;
using System.Windows.Threading;
using System.Threading.Tasks;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Coding4Fun.PanoHead.Resources;

namespace Coding4Fun.PanoHead
{
    /// <summary>
    /// A helper class to manage the communications with the Pano Head Gadgeteer App
    /// </summary>
    public class PanoControl
    {
        private StreamSocket _socket;
        private DataWriter _dataWriter;

        public StreamSocket Socket
        {
            get { return _socket; }
            set
            {
                _socket = value;
                _dataWriter = new DataWriter(_socket.OutputStream);

                SetConnectedStatus(IsConnected);
            }
        }

        /// <summary>
        /// Sets the connected status of the view model.
        /// </summary>
        /// <param name="status">The status as a bool value.</param>
        private void SetConnectedStatus(Boolean status)
        {
            App.panoViewModel.IsConnected = status;

            App.panoViewModel.Status = status ? AppResources.Connected : AppResources.DeviceIsNotConnected;
        }

        public PanoControl()
        {
            SetConnectedStatus(false);
        }

        private void CheckForDevice()
        {
            if (IsConnected)
            {
                SetConnectedStatus(true);
            }
            else
            {
                SetConnectedStatus(false);
                throw new InvalidOperationException(AppResources.DeviceIsNotConnected);
            }
        }

        public async Task SpinTheLights()
        {
            await SendCommand(Commands.CmdLeds);
        }

        public async Task TakePicture()
        {
            await SendCommand(Commands.CmdShut);
        }

        public async Task Left()
        {
            await SendCommand(Commands.CmdLeft);
        }

        public async Task Right()
        {
            await SendCommand(Commands.CmdRight);
        }

        public async Task Stop()
        {
            await SendCommand(Commands.CmdStop);
        }

        public async Task Pano()
        {
            await SendCommand(String.Format("{0},{1}", Commands.CmdPano, App.panoViewModel.MakePanoCommand()));
        }

        /// <summary>
        /// Sends the specified command over the Bluetooth socket.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <returns></returns>
        public DataWriterStoreOperation SendCommand(string command)
        {
            CheckForDevice();

            _dataWriter.WriteString(String.Format("@{0}#", command));

            return _dataWriter.StoreAsync();
        }

        public void CloseSocket(Dispatcher dispatcher)
        {
            try
            {
                if (_socket != null)
                {
                    _socket.Dispose();
                    _socket = null;
                }
                SetConnectedStatus(false);
            }
            catch (Exception f)
            {
                SetConnectedStatus(false);
                dispatcher.BeginInvoke(() => MessageBox.Show(String.Format(AppResources.ErrorClosingSocket, f.Message)));
            }
        }

        public bool IsConnected
        {
            get
            {
                return (_socket != null && _dataWriter != null);
            }
        }
    }
}
